#include "parse.h"

#define S_GET(s)   (*((*s)++))
#define S_UNGET(s) (*(--(*s)))
#define S_END(s)

#define IS_WHITESPACE(ch) (ch == ' '  || ch == '\r' || ch == '\n'|| ch == '\t')
#define IS_ALPHA(ch) ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
#define IS_NUMERIC(ch) (ch >= '0' && ch <= '9')
#define IS_ALPHANUMERIC(ch) (IS_ALPHA(ch) || IS_NUMERIC(ch))
#define IS_OTHER(ch) (!IS_ALPHANUMERIC(ch) && !IS_WHITESPACE(ch))
#define IS_EOF(ch) (ch == EOF)
#define IS_NULL(ch) (ch == 0)

static char t_ch;
static char input[TOKEN_MAX_LEN];

void 
print_token(token_t * t)
{
    switch(t->type)
    {
    case T_IDENTIFIER:
        printf("identifier: %s\n", t->text);
        break;

    case T_WHITESPACE:
        break;

    case T_OTHER:
        printf("other token: %s\n", t->text);
        break;

    default:
        printf("unknown token: %s\n", t->text);
        break;
    }
}

char 
get_whitespace(char **s, char *buff, int *len)
{
    while(1) {
        t_ch = S_GET(s);
        if (!IS_WHITESPACE(t_ch) || IS_NULL(t_ch)) break;
        buff[(*len)++] = t_ch;
    }
    return S_UNGET(s);
}

char 
get_alphanumeric(char **s, char *buff, int *len)
{
    while(1) {
        t_ch = S_GET(s);
        if ((!IS_ALPHANUMERIC(t_ch) && t_ch != '_') || IS_NULL(t_ch))  break;
        buff[(*len)++] = t_ch;
    }
    return S_UNGET(s);
}

int 
get_next_token(char **s, token_t *t)
{
    char  *text = (t->text);
    int   *length = &(t->length);

    memset(t, 0, sizeof(token_t));

    *length = 0;
    t->type = T_EOF;

    t_ch = S_GET(s);

    if (IS_ALPHANUMERIC(t_ch)) {
        (void) S_UNGET(s);
        get_alphanumeric(s, text, length);
        t->type = T_IDENTIFIER;

    } else if (IS_WHITESPACE(t_ch)) {
        (void) S_UNGET(s);
        get_whitespace(s, text, length);
        t->type = T_WHITESPACE;

        get_next_token(s, t);

    } else if (IS_NULL(t_ch)) {
        t->type = T_EOF;

    } else if (IS_OTHER(t_ch)) {
        text[(*length)++] = t_ch;
        t->type = T_OTHER;

    } else {
        t->type = T_ERROR;

    }

    text[*length] = 0;
    return (1);
}

int 
get_next_int(char **s)
{
    int v;
    token_t t;
    get_next_token(s, &t);
    sscanf(t.text, "%d", &v);
    return v;
}


char *
get_input_line()
{
    int ch = 0;
    int c = 0;
    memset(input, 0, TOKEN_MAX_LEN);
    while (((ch = getchar()) != '\n') && (c < TOKEN_MAX_LEN - 1)) {
        input[c++] = ch;
    }

    return (char*)input;
}

